<template>
  <h3>烟花爆炸</h3>
</template>

<script>
export default {
  name: "index",
  methods:{
    show(){
      class Circle {
        constructor({ origin, speed, color, angle, context }) {
          this.origin = origin
          this.position = { ...this.origin }
          this.color = color
          this.speed = speed
          this.angle = angle
          this.context = context
          this.renderCount = 0
        }

        draw() {
          this.context.fillStyle = this.color
          this.context.beginPath()
          this.context.arc(this.position.x, this.position.y, 2, 0, Math.PI * 2)
          this.context.fill()
        }

        move() {
          this.position.x = (Math.sin(this.angle) * this.speed) + this.position.x
          this.position.y = (Math.cos(this.angle) * this.speed) + this.position.y + (this.renderCount * 0.3)
          this.renderCount++
        }
      }

      class Boom {
        constructor({ origin, context, circleCount = 10, area }) {
          this.origin = origin
          this.context = context
          this.circleCount = circleCount
          this.area = area
          this.stop = false
          this.circles = []
        }

        randomArray(range) {
          const length = range.length
          const randomIndex = Math.floor(length * Math.random())
          return range[randomIndex]
        }

        randomColor() {
          const range = ['8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
          return '#' + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range)
        }

        randomRange(start, end) {
          return (end - start) * Math.random() + start
        }

        init() {
          for (let i = 0; i < this.circleCount; i++) {
            const circle = new Circle({
              context: this.context,
              origin: this.origin,
              color: this.randomColor(),
              angle: this.randomRange(Math.PI - 1, Math.PI + 1),
              speed: this.randomRange(1, 6)
            })
            this.circles.push(circle)
          }
        }

        move() {
          this.circles.forEach((circle, index) => {
            if (circle.position.x > this.area.width || circle.position.y > this.area.height) {
              return this.circles.splice(index, 1)
            }
            circle.move()
          })
          if (this.circles.length == 0) {
            this.stop = true
          }
        }

        draw() {
          this.circles.forEach(circle => circle.draw())
        }
      }

      class CursorSpecialEffects {
        constructor() {
          this.computerCanvas = document.createElement('canvas')
          this.renderCanvas = document.createElement('canvas')

          this.computerContext = this.computerCanvas.getContext('2d')
          this.renderContext = this.renderCanvas.getContext('2d')

          this.globalWidth = window.innerWidth
          this.globalHeight = window.innerHeight

          this.booms = []
          this.running = false
        }

        handleMouseDown(e) {
          const boom = new Boom({
            origin: { x: e.clientX, y: e.clientY },
            context: this.computerContext,
            area: {
              width: this.globalWidth,
              height: this.globalHeight
            }
          })
          boom.init()
          this.booms.push(boom)
          this.running || this.run()
        }

        handlePageHide() {
          this.booms = []
          this.running = false
        }

        init() {
          const style = this.renderCanvas.style
          style.position = 'fixed'
          style.top = style.left = 0
          style.zIndex = '999999999999999999999999999999999999999999'
          style.pointerEvents = 'none'

          style.width = this.renderCanvas.width = this.computerCanvas.width = this.globalWidth
          style.height = this.renderCanvas.height = this.computerCanvas.height = this.globalHeight

          document.body.append(this.renderCanvas)

          window.addEventListener('mousedown', this.handleMouseDown.bind(this))
          window.addEventListener('pagehide', this.handlePageHide.bind(this))
        }

        run() {
          this.running = true
          if (this.booms.length == 0) {
            return this.running = false
          }

          requestAnimationFrame(this.run.bind(this))

          this.computerContext.clearRect(0, 0, this.globalWidth, this.globalHeight)
          this.renderContext.clearRect(0, 0, this.globalWidth, this.globalHeight)

          this.booms.forEach((boom, index) => {
            if (boom.stop) {
              return this.booms.splice(index, 1)
            }
            boom.move()
            boom.draw()
          })
          this.renderContext.drawImage(this.computerCanvas, 0, 0, this.globalWidth, this.globalHeight)
        }
      }

      const cursorSpecialEffects = new CursorSpecialEffects()
      cursorSpecialEffects.init()
    }
  },
  mounted() {
    this.show()
  }
}
</script>

<style scoped>

</style>
